#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/wait.h>
#include <sqlite3.h>


#include "pack.h"
#include "database.h"
#include "logger.h"

static sqlite3* open_database(const char *filename) 
{
    sqlite3 		*db 		= NULL;
    int 			rc 			= sqlite3_open("./socket.db", &db);
    if (rc != SQLITE_OK) 
	{
        log_warn( "can not open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);  
        return NULL;
    }
    return db;
}

sqlite3* init_data(const char *db_name, const char *table_name) 
{
    sqlite3 		*db 		= NULL;
    char 			sql[256];
    char 			*err_msg 	= NULL;

    if (!db_name || !table_name) 
	{
        log_warn("%s() Invalid input arguments\n", __func__);
        return NULL;
    }

    int rc = sqlite3_open(db_name, &db);
    if (rc != SQLITE_OK) 
	{
        log_warn( "Unable to open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return NULL;
    }

    snprintf(sql, sizeof(sql), "CREATE TABLE IF NOT EXISTS %s (msg_name, msg_time, msg_temp);", table_name);
    rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
    if (rc != SQLITE_OK) 
	{
        log_warn("SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(db);
        return NULL;
    }
	printf("Table %s created or already exists\n",table_name);
    sqlite3_free(err_msg);
    return db;
}

void create_table(const char *filename) 
{
    sqlite3 		*db 		= open_database(filename);
    char 			*zErrMsg 	= NULL;
    int 			rc 			= -1;
    const char 		*sql 		= "CREATE TABLE IF NOT EXISTS staging(" \
								   "msg_name CHAR NOT NULL," \
								   "msg_time CHAR NOT NULL," \
								   "msg_temp CHAR NOT NULL);";

    rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg);

    if (rc != SQLITE_OK) 
	{
        log_warn( "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } 
	else 
	{
        log_info( "Table created successfully\n");
    }

    sqlite3_close(db);
}

void close_table(sqlite3* db)
{
	if(db!=NULL)
	{
		sqlite3_close(db);
	}
}

int read_data(sqlite3 *db, pack_data_t *data) 
{
    sqlite3_stmt *stmt;
    const char *sql = "SELECT msg_name, msg_time, msg_temp FROM staging;";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) 
	{
        log_warn("Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return -1;
    }

    if ((rc = sqlite3_step(stmt)) == SQLITE_ROW) 
	{
        // 读取字段数据并存储到结构体
        strcpy(data->id, (char *)sqlite3_column_text(stmt, 0));
        strcpy(data->time, (char *)sqlite3_column_text(stmt, 1));
        data->temperature = (float)sqlite3_column_double(stmt, 2);

        log_info("Name: %s, Time: %s, Temperature: %.2f\n", data->id, data->time, data->temperature);

        sqlite3_finalize(stmt);
        return 0;  // 成功读取一行数据
    }
	else if (rc == SQLITE_DONE) 
	{
        // 执行成功但无数据可读
        sqlite3_finalize(stmt);
        return 1;  // 没有数据可读
    }
	else 
	{
        // 读取过程中发生错误
        log_warn("Read error: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return -2;
    }
}

void insert_data(sqlite3 *db, pack_data_t *data) 
{
    sqlite3_stmt *stmt;
    const char *sql = "INSERT INTO staging (msg_name, msg_time, msg_temp) VALUES (?, ?, ?);";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) 
	{
        log_warn("Prepare failed: %s\n", sqlite3_errmsg(db));
        return;
    }

    sqlite3_bind_text(stmt, 1, data->id, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, data->time, -1, SQLITE_STATIC);
    sqlite3_bind_double(stmt, 3, data->temperature);

    if ((rc = sqlite3_step(stmt)) != SQLITE_DONE) 
	{
        log_warn("Insert error: %s\n", sqlite3_errmsg(db));
    }
	else 
	{
        log_info("Data inserted successfully\n");
    }
    sqlite3_finalize(stmt);
}

void delete_data(sqlite3 *db, pack_data_t *data) 
{
    sqlite3_stmt *stmt;
    const char *sql = "DELETE FROM staging WHERE msg_time = ?;";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);

    if (rc == SQLITE_OK) 
	{
        sqlite3_bind_text(stmt, 1, data->time, -1, SQLITE_STATIC);
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_DONE) 
		{
            log_warn("Delete error: %s\n", sqlite3_errmsg(db));
        }
		else 
		{
            log_info("Data deleted successfully\n");
        }
    } 
	else 
	{
        log_warn("Prepare failed: %s\n", sqlite3_errmsg(db));
    }
    sqlite3_finalize(stmt);
}

int pop_data(sqlite3 *db, pack_data_t *data) 
{
    sqlite3_stmt *stmt;
    const char *sql = "SELECT * FROM staging LIMIT 1;";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) 
	{
        log_warn("Prepare failed: %s\n", sqlite3_errmsg(db));
        return -1;
    }

    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) 
	{
        strcpy(data->id, (const char *)sqlite3_column_text(stmt, 0));
        strcpy(data->time, (const char *)sqlite3_column_text(stmt, 1));
        data->temperature = (float)sqlite3_column_double(stmt, 2);

        delete_data(db, data); // Use the same struct for deletion

        sqlite3_finalize(stmt);
        return 0;
    }
	else if (rc == SQLITE_DONE) 
	{
        sqlite3_finalize(stmt);
        return 1;
    }
	else 
	{
        log_warn("Read error: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return -2;
    }
}

